﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Collections;
using System.Runtime.InteropServices;
using System.Helpers;
using System.Net;
using System.Runtime.Serialization.Formatters.Binary;
using System.IO;
using System.Net.Sockets;
/* 对报文字进行整理替换 ，并且提供一些十六进制数据转化类型的方法 */
namespace DataProcessModule
{
    public static class Utilities
    {
        public static double pi = 3.1415926535897932384626;
        public static double a = 6378245.0;
        public static double ee = 0.00669342162296594323;
        #region 方法
        /// <summary>
        /// 恢复转义
        /// </summary>
        /// <returns></returns>
        public static byte[] UnConvertFlag(byte[] inst,int start,int end)
        {
            //byte[] inst = new byte[] { 0x30, 0x08, 0x7d,0x02, 0x55, 0x02, 0x7d,0x01, 0x12, 0x7d,0x02, 0x7d,0x01};
            try
            {
                int count = 0;
                if (end > inst.Length)
                {
                    end = inst.Length;
                }

                try
                {
                    for (int i = start; i < end; i++)
                    {
                        if (i == inst.Length - 1)
                        {
                            break;
                        }

                        if ((inst[i] == 0x7d && inst[i + 1] == 0x01) || (inst[i] == 0x7d && inst[i + 1] == 0x02))
                        {
                            count++;
                        }
                    }
                }
                catch (Exception ex)
                {
                    string msg = string.Empty;
                    for (int i = 0; i < inst.Length; i++)
                    {
                        msg += Convert.ToString(inst[i], 16).PadLeft(2, '0');
                    }

                    //LOGHelper.WriteLog("反向转义统计转义总数时出错: "+ msg);
                }

                if (count == 0)
                {
                    return inst;
                }
                
                byte[] subinst = new byte[inst.Length - count];

                int j = 0;
                for (int i = 0; i < inst.Length; i++)
                {
                    if (i == inst.Length - 1 && inst[i] == 0x7d)
                    {
                        subinst[j] = inst[i];
                        break;
                    }

                    if (j < subinst.Length)
                    {
                        try
                        {
                            if (inst[i] == 0x7d && inst[i + 1] == 0x01)
                            {
                                subinst[j] = 0x7d;
                                //// 跳过i+1
                                i++;
                            }
                            else if (inst[i] == 0x7d && inst[i + 1] == 0x02)
                            {
                                subinst[j] = 0x7e;
                                i++;
                            }
                            else
                            {
                                subinst[j] = inst[i];
                            }

                            j++;
                        }
                        catch (Exception ex)
                        {
                            string msg = string.Empty;
                            for (int loop = 0; loop < inst.Length; loop++)
                            {
                                msg += Convert.ToString(inst[loop], 16).PadLeft(2, '0');
                            }

                            //LOGHelper.WriteLog("反向转义时出错: " + msg);
                        }
                    }
                }

                return subinst;
            }
            catch (Exception ex)
            {
                return null;
            }
        }

        /// <summary>
        /// 转义
        /// </summary>
        /// <returns></returns>
        public static byte[] ConvertFlag()
        {
            byte[] inst = new byte[]{0x30,0x08,0x7e,0x55,0x02,0x7d,0x12,0x7e,0x7d};

            int count = 0;
            for (int i = 0; i < inst.Length; i++)
            {
                if (inst[i] == 0x7e || inst[i] == 0x7d)
                {
                    count++;
                }
            }

            if (count == 0)
            {
                return inst;
            }

            byte[] subinst = new byte[inst.Length + count];

            int j = 0;
            for (int i = 0; i < inst.Length; i++)
            {
                if (j < subinst.Length)
                {
                    if (inst[i] == 0x7e)
                    {
                        subinst[j] = 0x7d;
                        subinst[++j] = 0x02;
                    }
                    else if (inst[i] == 0x7d)
                    {
                        subinst[j] = 0x7d;
                        subinst[++j] = 0x01;
                    }
                    else
                    {
                        subinst[j] = inst[i];
                    }

                    j++;
                }
            }

            return subinst; 
        }

        /// <summary>
        /// 字节的异或运算
        /// </summary>
        /// <param name="data">要运算的字节数组</param>
        /// <returns>异或结果</returns>
        public static byte StreamXOR(byte[] data)
        {
            byte result = data[0];
            for (int i = 1; i < data.Length; i++)
            {
                result = (byte)(result ^ data[i]);
            }

            return result;
        }

        /// <summary>
        /// 字节的异或运算
        /// </summary>
        /// <param name="data">数据</param>
        /// <param name="start">开始计算位置</param>
        /// <param name="end">计算结束位置</param>
        /// <returns>校验码</returns>
        public static byte StreamXOR(byte[] data,int start,int end)
        {
            byte result = data[start];
            for (int i = start + 1; i <= end; i++)
            {
                result = (byte)(result ^ data[i]);
            }

            return result;
        }

        /// <summary>
        /// 位数据转换为整数
        /// </summary>
        /// <param name="bitarray"></param>
        /// <returns></returns>
        public static UInt32 BitArrayToInt(BitArray bitarray)
        {
            UInt32 ret = 0;
            for (Int32 i = 0; i < bitarray.Length; i++)
            {
                if (bitarray.Get(i))
                {
                    ret |= (UInt32)(1 << i);
                }
            }
            return ret;
        }

        /// <summary>
        /// 结构体转换为字节流
        /// </summary>
        /// <param name="structure">结构体</param>
        /// <returns>字节流</returns>
        public static Byte[] StructToBytes(Object structure) 
        {

            Int32 size = Marshal.SizeOf(structure); 
            Console.WriteLine(size); 
            IntPtr buffer = Marshal.AllocHGlobal(size); 
            try 
            { 
                Marshal.StructureToPtr(structure, buffer, false); 
                Byte[] bytes = new Byte[size]; 
                Marshal.Copy(buffer, bytes, 0, size); 
                return bytes; 
            } 
            finally 
            { 
                Marshal.FreeHGlobal(buffer); 
            } 
        }

        /// <summary>
        /// 字节流换为结构体转
        /// </summary>
        /// <param name="structure">字节流</param>
        /// <returns>结构体</returns>
        public static Object BytesToStruct(Byte[] bytes, Type strcutType) 
        { 
            Int32 size = Marshal.SizeOf(strcutType); 
            IntPtr buffer = Marshal.AllocHGlobal(size); 
            try 
            { 
                Marshal.Copy(bytes, 0, buffer, size); 
                return Marshal.PtrToStructure(buffer, strcutType); 
            } 
            finally 
            { 
                Marshal.FreeHGlobal(buffer); 
            } 
        }

        /// <summary>
        /// 按BIT位计算
        /// </summary>
        /// <param name="buffer"></param>
        /// <param name="start"></param>
        /// <param name="end"></param>
        /// <returns></returns>
        public static UInt16 CalcBitValue(UInt16 value, int start, int end)
        {
            byte[] property = BitConverter.GetBytes(value);
            BitArray bitArray = new BitArray(property);
            BitArray subBitArray = new BitArray(10);

            for (int i = start; i < end; i++)
            {
                subBitArray[i] = bitArray[i];
            }

            return (UInt16)Utilities.BitArrayToInt(subBitArray);
        }

        /// <summary>
        /// 十进制转为二进制
        /// </summary>
        /// <param name="number"></param>
        /// <returns></returns>
        public static string DecimalToBinary(int number)
        {
            int numbin = 0;
            string strnumbin = string.Empty;
            while (number > 0)
            {
                numbin = number % 2;
                number = number / 2;
                strnumbin += numbin.ToString();
            }

            return strnumbin;
        }

        ///<summary> 
        /// 序列化 
        /// </summary> 
        /// <param name="data">要序列化的对象</param> 
        /// <returns>返回存放序列化后的数据缓冲区</returns> 
        public static byte[] Serialize(object data)
        {
            BinaryFormatter formatter = new BinaryFormatter();
            MemoryStream rems = new MemoryStream();
            formatter.Serialize(rems, data);
            return rems.GetBuffer();
        }

        /// <summary> 
        /// 反序列化 
        /// </summary> 
        /// <param name="data">数据缓冲区</param> 
        /// <returns>对象</returns> 
        public static object Deserialize(byte[] data)
        {
            BinaryFormatter formatter = new BinaryFormatter();
            MemoryStream rems = new MemoryStream(data);
            data = null;
            return formatter.Deserialize(rems);
        }

        #endregion

        /// <summary>
        /// 从字节流中得到时间
        /// </summary>
        /// <param name="buffer"></param>
        /// <param name="offset"></param>
        /// <param name="add8Hours"></param>
        /// <returns></returns>
        public static DateTime ToDateTime(byte[] buffer, ref int offset, bool add8Hours = false)
        {
            int year = BC.BCDToByte(buffer[offset++]) + 2000;
            int month = BC.BCDToByte(buffer[offset++]);
            int day = BC.BCDToByte(buffer[offset++]);
            int hour = BC.BCDToByte(buffer[offset++]);
            int minute = BC.BCDToByte(buffer[offset++]);
            int second = BC.BCDToByte(buffer[offset++]);
            //if (ValidateHelper.IsValidateDateTime(year, month, day, hour, minute, second))
            return new DateTime(year, month, day, hour, minute, second);
            //return DateTime.MinValue;
        }

        /// <summary>
        /// 从字节流中得到日期
        /// </summary>
        /// <param name="buffer"></param>
        /// <param name="offset"></param>
        /// <param name="add8Hours"></param>
        /// <returns></returns>
        public static DateTime ToDate(byte[] buffer, ref int offset)
        {
            int year = BC.BCDToByte(buffer[offset++]) + 2000;
            int month = BC.BCDToByte(buffer[offset++]);
            int day = BC.BCDToByte(buffer[offset++]);

            //if (ValidateHelper.IsValidateDateTime(year, month, day, 0, 0, 0))
            return new DateTime(year, month, day, 0, 0, 0);
            //return DateTime.MinValue;
        }

        public static void WriteDataTime(DateTime time, byte[] buffer, ref int offset)
        {
            string timeStr = (time).ToString("yyMMddHHmmss");
            BC.WriteBCD(timeStr, 0, timeStr.Length, buffer, ref offset);
        }

        /// <summary>
        /// 获取
        /// </summary>
        /// <param name="item"></param>
        public static void GetOffsetGps(double lon , double lat)
        {
            //double lon = item.Lon;
            //double lat = item.Lat;

            /* 合众算法存在性能问题
            // 加密运算（对国内地图纠偏）
            OffsetData.Encrypt(lon, lat, out xr, out yr);
            if (xr != 0 || yr != 0)
            {
                item.OffsetLon = (float)(xr - lon);
                item.OffsetLat = (float)(yr - lat);
            }
            */

            if (outOfChina(lat, lon))
            {
                return;
            }

            double dLat = transformLat(lon - 105.0, lat - 35.0);
            double dLon = transformLon(lon - 105.0, lat - 35.0);
            double radLat = lat / 180.0 * pi;
            double magic = Math.Sin(radLat);
            magic = 1 - ee * magic * magic;
            double sqrtMagic = Math.Sqrt(magic);
            dLat = (dLat * 180.0) / ((a * (1 - ee)) / (magic * sqrtMagic) * pi);
            dLon = (dLon * 180.0) / (a / sqrtMagic * Math.Cos(radLat) * pi);

            //item.OffsetLon = (float)dLon;
            //item.OffsetLat = (float)dLat;
        }

        public static bool outOfChina(double lat, double lon)
        {
            if (lon < 72.004 || lon > 137.8347)
                return true;
            if (lat < 0.8293 || lat > 55.8271)
                return true;
            return false;
        }

        public static double transformLat(double x, double y)
        {
            double ret = -100.0 + 2.0 * x + 3.0 * y + 0.2 * y * y + 0.1 * x * y
                    + 0.2 * Math.Sqrt(Math.Abs(x));
            ret += (20.0 * Math.Sin(6.0 * x * pi) + 20.0 * Math.Sin(2.0 * x * pi)) * 2.0 / 3.0;
            ret += (20.0 * Math.Sin(y * pi) + 40.0 * Math.Sin(y / 3.0 * pi)) * 2.0 / 3.0;
            ret += (160.0 * Math.Sin(y / 12.0 * pi) + 320 * Math.Sin(y * pi / 30.0)) * 2.0 / 3.0;
            return ret;
        }

        public static double transformLon(double x, double y)
        {
            double ret = 300.0 + x + 2.0 * y + 0.1 * x * x + 0.1 * x * y + 0.1
                    * Math.Sqrt(Math.Abs(x));
            ret += (20.0 * Math.Sin(6.0 * x * pi) + 20.0 * Math.Sin(2.0 * x * pi)) * 2.0 / 3.0;
            ret += (20.0 * Math.Sin(x * pi) + 40.0 * Math.Sin(x / 3.0 * pi)) * 2.0 / 3.0;
            ret += (150.0 * Math.Sin(x / 12.0 * pi) + 300.0 * Math.Sin(x / 30.0
                    * pi)) * 2.0 / 3.0;
            return ret;
        }

        public static string GetLocalIP()
        {
            try
            {
                string HostName = Dns.GetHostName(); //得到主机名
                IPHostEntry IpEntry = Dns.GetHostEntry(HostName);
                for (int i = 0; i < IpEntry.AddressList.Length; i++)
                {
                    //从IP地址列表中筛选出IPv4类型的IP地址
                    //AddressFamily.InterNetwork表示此IP为IPv4,
                    //AddressFamily.InterNetworkV6表示此地址为IPv6类型
                    if (IpEntry.AddressList[i].AddressFamily == AddressFamily.InterNetwork)
                    {
                        return IpEntry.AddressList[i].ToString();
                    }
                }
                return "";
            }
            catch (Exception ex)
            {
                return "";
            }
        }

        public static string ToHexString(byte[] bytes) // 0xae00cf => "AE00CF "
        {
            string hexString = string.Empty;
            if (bytes != null)
            {
                StringBuilder strB = new StringBuilder();
                for (int i = 0; i < bytes.Length; i++)
                {
                    strB.Append(bytes[i].ToString("X2"));
                }
                hexString = strB.ToString();
            }
            return hexString;
        }
    }
}
